#ifndef _spi_flash_h_
#define _spi_flash_h_

#include "types.h"

typedef struct
{
	volatile u32 CMD0;
	volatile u32 CMD1;
	volatile u32 CMD2;
	volatile u32 CMD3;
	volatile u32 CR;
	volatile u32 ACTR;
	volatile u32 SR;
	volatile u32 rsv_0;

	volatile u32 ICR;
	volatile u32 ISR;
	volatile u32 SPISR;
	volatile u32 SPIFSR;

	volatile u32 XIPCMD;
	volatile u32 rsv_1[7];

	volatile u32 REVISION;
	volatile u32 FEATURE;
	volatile u32 rsv_2[42];

	volatile u32 DR;
}SPI_REG;

typedef enum
{
	STATUS_0 = 0,
	STATUS_1,
	STATUS_2
}STATUS_REGS;

struct ftspi020_cmd {
	u32    cq0;
	u32    cq1;
	u32    cq2;
	u32    cq3;
};

#define SPI0               0
#define SPI1               1
#define SPI_NOR_NORMAL     0x00100000
#define SPI_NOR_FAST       0x00200000
#define SPI_NOR_DUAL       0x00400000
#define SPI_NOR_QUAD       0x00800000

/* Erase commands */
#define CMD_ERASE_4K			0x20
#define CMD_ERASE_CHIP			0xc7
#define CMD_ERASE_64K			0xd8
#define CMD_ERASE_32K			0x52

#define ERASE_SIZE_4K           4096
#define FLASH_PAGE_SIZE         256

/* Write commands */
#define CMD_WRITE_STATUS_0		0x01
#define CMD_WRITE_STATUS_1		0x31
#define CMD_WRITE_STATUS_2		0x11
#define CMD_PAGE_PROGRAM		0x02
#define CMD_WRITE_DISABLE		0x04
#define CMD_WRITE_ENABLE		0x06
#define CMD_QUAD_PAGE_PROGRAM		0x32

/* Read commands */
#define CMD_READ_ARRAY_SLOW		0x03
#define CMD_READ_ARRAY_FAST		0x0b
#define CMD_READ_DUAL_OUTPUT_FAST	0x3b
#define CMD_READ_DUAL_IO_FAST		0xbb
#define CMD_READ_QUAD_OUTPUT_FAST	0x6b
#define CMD_READ_QUAD_IO_FAST		0xeb
#define CMD_READ_ID			0x9f
#define CMD_READ_STATUS0		0x05
#define CMD_READ_STATUS1		0x35
#define CMD_READ_STATUS2		0x15
#define CMD_READ_CONFIG			0x35
#define CMD_FLAG_STATUS			0x70

/*
 * Status Register
 */
#define SPI_NOR_PROTECTION_BP0TO4  (0x1f << 2)
#define SPI_NOR_PROTECTION_BP0TO3  (0x0f << 2)
#define SPI_NOR_PROTECTION_BP0TO2  (0x07 << 2)

#define	SPI_NOR_FEATURE_STATUS_WEL         (1 << 1)	/* Write enable latch */
#define	SPI_NOR_FEATURE_STATUS_OIP         (1 << 0)	/* Operation in progress */
#define	SPI_NOR_FEATURE_OTP_QUAD_ENABLE    (1 << 1)	/* Quad enable */

/*
 * Command Queue Second Word Register offset 0x4
 */
#define FTSPI020_CMD1_CONT_READ_MODE_EN     (1 << 28)
#define FTSPI020_CMD1_CONT_READ_MODE_DIS    (0 << 28)

#define FTSPI020_CMD1_OP_CODE_0_BYTE        (0 << 24)
#define FTSPI020_CMD1_OP_CODE_1_BYTE        (1 << 24)
#define FTSPI020_CMD1_OP_CODE_2_BYTE        (2 << 24)

#define FTSPI020_CMD1_DUMMY_CYCLE(x)        (((x) & 0xff) << 16)

#define FTSPI020_CMD1_ADDR_BYTES(x)	        ((x & 0x7) << 0)

/*
 * Command Queue Fourth Word Register offset 0xc
 */
#define FTSPI020_CMD3_INSTR_CODE(x)         (((x) & 0xff) << 24)

#define FTSPI020_CMD3_CONT_READ_CODE(x)     (((x) & 0xff) << 16)

#define FTSPI020_CMD3_CE(x)                 (((x) & 0x3) << 8)

#define FTSPI020_CMD3_SERIAL_MODE           (0 << 5)
#define FTSPI020_CMD3_DUAL_MODE             (1 << 5)
#define FTSPI020_CMD3_QUAD_MODE             (2 << 5)
#define FTSPI020_CMD3_DUAL_IO_MODE          (3 << 5)
#define FTSPI020_CMD3_QUAD_IO_MODE          (4 << 5)

#define FTSPI020_CMD3_DTR_MODE_EN           (1 << 4)
#define FTSPI020_CMD3_DTR_MODE_DIS          (0 << 4)

#define FTSPI020_CMD3_STS_SW_READ           (1 << 3)
#define FTSPI020_CMD3_STS_HW_READ           (0 << 3)

#define FTSPI020_CMD3_RD_STS_EN             (1 << 2)
#define FTSPI020_CMD3_RD_STS_DIS            (0 << 2)

#define FTSPI020_CMD3_WRITE                 (1 << 1)
#define FTSPI020_CMD3_READ                  (0 << 1)

#ifndef CONFIG_FTSPI020_NAND_V1_1_0
#define FTSPI020_CMD3_INTR_EN               (0 << 0) // (1 << 0) -> (0 << 0)
#else
#define FTSPI020_CMD3_INTR_EN               (0 << 0)
#endif

/*
 * Control Register offset 0x10
 */
#define FTSPI020_CTRL_DAMR_PORT             (1 << 20)

#define FTSPI020_CTRL_READY_LOC_MASK        (~(0x7 << 16))
#define FTSPI020_CTRL_READY_LOC(x)          (((x) & 0x7) << 16)

#define FTSPI020_CTRL_ABORT                 (1 << 8)

#define FTSPI020_CTRL_CLK_MODE_MASK         (~(0x1 << 4))
#define FTSPI020_CTRL_CLK_MODE_0            (0 << 4)
#define FTSPI020_CTRL_CLK_MODE_3            (1 << 4)

#define FTSPI020_CTRL_CLK_DIVIDER_MASK      (~(0x3 << 0))
#define FTSPI020_CTRL_CLK_DIVIDER_2         (0 << 0)
#define FTSPI020_CTRL_CLK_DIVIDER_4         (1 << 0)
#define FTSPI020_CTRL_CLK_DIVIDER_6         (2 << 0)
#define FTSPI020_CTRL_CLK_DIVIDER_8         (3 << 0)

/*
 * Status Register offset 0x18
 */
#define	FTSPI020_STS_RFR                    (1 << 1)	/* RX FIFO ready */

#define	FTSPI020_STS_TFR                    (1 << 0)	/* TX FIFO ready */

/*
 * Interrupt Control Register offset 0x20
 */
#define	FTSPI020_ICR_RFTH(x)                (((x) & 0x3) << 12)	/* RX FIFO threshold */

#define	FTSPI020_ICR_TFTH(x)                (((x) & 0x3) << 8)	/* TX FIFO threshold */

#define	FTSPI020_ICR_CMD_CMPL               (1 << 1)	/* Command complete enable */
#define	FTSPI020_ICR_DMA                    (1 << 0)	/* DMA handshake enable */

/*
 * Interrupt Status Register offset 0x24
 */
#define	FTSPI020_ISR_CMD_CMPL               (1 << 0)	/* Command complete status */

/*
 * Feature Register offset 0x54
 */
#define FTSPI020_FEATURE_CLK_MODE(reg)      (((reg) >> 25) & 0x1)

#define FTSPI020_FEATURE_DTR_MODE(reg)      (((reg) >> 24) & 0x1)

#define FTSPI020_FEATURE_RXFIFO_DEPTH(reg)  (((reg) >>  8) & 0xff)

#define FTSPI020_FEATURE_TXFIFO_DEPTH(reg)  (((reg) >>  0) & 0xff)

#define min_t(x,y) ( x < y ? x: y )

#define	EIO 5		/* I/O error */
#define	EBUSY 16	/* Mount device busy */
#define	EINVAL 22	/* Invalid argument */
#define ETIMEDOUT 116		/* Connection timed out */

void SPI_FLASH_Init(void);
UINT32 SPI_FLASH_BufferRead(u8* pBuffer, u32 ReadAddr, u32 NumByteToRead);
UINT32 SPI_FLASH_BufferWrite(unsigned char* pBuffer, unsigned int WriteAddr, unsigned int NumByteToWrite);
UINT32 SPI_FLASH_BufferErase(u32 EraseAddr, u32 NumByteToErase);
void Flash_APITest(void);
UINT32 SPI_FLASH_BufferRead_DMA(u8* pBuffer, u32 ReadAddr, u32 NumByteToRead);
#endif
